package co.fitstart.mobile.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.BusinessException;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.support.Result;
import com.demo2do.core.support.handler.FileUploadHanlder;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.DateUtils;

import co.fitstart.entity.Constant;
import co.fitstart.entity.coach.CoachRestCalendar;
import co.fitstart.entity.coach.CoachRestType;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.course.schedule.CourseScheduleAttribute;
import co.fitstart.entity.course.schedule.CourseScheduleCancelRecord;
import co.fitstart.entity.principal.Principal;
import co.fitstart.entity.principal.PrincipalMessage;
import co.fitstart.entity.site.RoomScheduleRecord;
import co.fitstart.entity.site.RoomType;
import co.fitstart.entity.site.Site;
import co.fitstart.entity.user.Student;
import co.fitstart.mobile.dao.support.ScheduleDaoSupport;
import co.fitstart.mobile.handler.TencentHandler;
import co.fitstart.mobile.service.CourseScheduleService;

/**
 * 
 * @author mohanlan
 *
 */
@Service("CourseScheduleService")
public class CourseScheduleServiceImpl implements CourseScheduleService {
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    @Autowired
    private ScheduleDaoSupport scheduleDaoSupport;

    @Autowired
    private FileUploadHanlder fileUploadHanlder;

    @Autowired
    private TencentHandler tencentHandler;
    
    /* (non-Javadoc)
     * @see co.fitstart.mobile.service.CourseScheduleService#mapCourseSchedule(co.fitstart.entity.principal.Principal, java.util.Date)
     */
    public Map<String, CourseSchedule> mapCourseSchedule(Principal coach, Date day, boolean experience) {
        //TODO
        List<CourseSchedule> courseSchedules = scheduleDaoSupport.listCourseSchedule(coach, day);
        Map<String, CourseSchedule> courseScheduleMap = CollectionUtils.constructMapValueFromList(courseSchedules, "dayhour");
        
        Map<String, CourseSchedule> result = new HashMap<String, CourseSchedule>();
        result.putAll(courseScheduleMap);
        for (String key : courseScheduleMap.keySet()) {
            String hour = StringUtils.split(key, "|")[1];
            Date occurHour = DateUtils.parseDate(DateFormatUtils.format(day, "yyyy-MM-dd ") + hour + ":00", "yyyy-MM-dd HH:mm:ss");
            
            Date beforeTime = org.apache.commons.lang3.time.DateUtils.addMinutes(occurHour, -30);
            if(!result.containsKey(DateFormatUtils.format(beforeTime, "yyyy-MM-dd|HH:mm"))) {
                result.put(DateFormatUtils.format(beforeTime, "yyyy-MM-dd|HH:mm"), courseScheduleMap.get(key));
            }
            
            Date afterTime = org.apache.commons.lang3.time.DateUtils.addMinutes(occurHour, 30);
            if(!result.containsKey(DateFormatUtils.format(afterTime, "yyyy-MM-dd|HH:mm"))) {
                result.put(DateFormatUtils.format(afterTime, "yyyy-MM-dd|HH:mm"), courseScheduleMap.get(key));
            }
            
        }
        
        return result;
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.CourseScheduleService#loadCourseSchedule(java.lang.Long)
     */
    public CourseSchedule loadCourseSchedule(Long courseScheduleId) {
        return genericDaoSupport.load(CourseSchedule.class, courseScheduleId);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.CourseScheduleService#loadCourseSchedule(co.fitstart.entity.user.Student, java.util.Date, java.lang.String[])
     */
    public CourseSchedule loadCourseSchedule(Student student, Date occurDate, String[] occurHours) {
        
        Map<String, Object> parameters = new HashMap<String, Object>(3);
        parameters.put("student", student);
        parameters.put("occurDate", occurDate);
        parameters.put("occurHours", occurHours);
        
        return genericDaoSupport.searchForObject("FROM CourseSchedule courseSchedule WHERE courseSchedule.disabled = false AND courseSchedule.student = :student AND courseSchedule.occurDate = :occurDate AND courseSchedule.occurHour in (:occurHours)", parameters, CourseSchedule.class);
    }
    
    
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.CourseScheduleService#editCourseSchedule(co.fitstart.entity.course.schedule.CourseSchedule, co.fitstart.entity.principal.Principal, co.fitstart.entity.site.RoomType, co.fitstart.entity.site.Site, java.util.Date, java.lang.String)
     */
    public void editCourseSchedule(CourseSchedule courseSchedule, Principal coach, RoomType roomType, Site site, Date day, String hour) {
        
        // FIXME should only update here
        RoomScheduleRecord roomScheduleRecord = courseSchedule.getRoomSchedule();
        if(roomScheduleRecord != null) {
            genericDaoSupport.update(roomScheduleRecord.updateTime(day, hour, site));
        }else {
            String roundCode = courseSchedule.getCourseRound().getCode();
            roomScheduleRecord = new RoomScheduleRecord(site, roundCode, day, hour, roomType, 1);
            genericDaoSupport.save(roomScheduleRecord);
        }
        
        // edit course schedule
        courseSchedule.editCoach(coach)
                      .editTime(day, hour)
                      .editSite(site)
                      .roomScheduleRecord(roomScheduleRecord);
        
        genericDaoSupport.update(courseSchedule);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.CourseScheduleService#cancelSchedule(co.fitstart.entity.course.schedule.CourseSchedule)
     */
    public void cancelSchedule(CourseSchedule courseSchedule) {
        
        Principal coach = courseSchedule.getCoach();
        
        // make message before update
        String message = "您的学员" + courseSchedule.getStudent().getName() + "，有课程取消："
                                  + DateFormatUtils.format(courseSchedule.getOccurDate()) + " " + courseSchedule.getOccurHour() 
                                  + "已被学员取消"
                                  + "，请去系统查看。";
        
        this.createPrincipalMessage(coach, message);
        
        // send message to coach
        tencentHandler.sendMessage(message, coach.getMobile());
        
        if(courseSchedule.getCourseType().isYear() || (courseSchedule.getCourseType().isIndividual() && !courseSchedule.getCourse().isExperience())) {
            if(DateUtils.isSameDay(new Date(), courseSchedule.getOccurDate())) {
                CourseScheduleCancelRecord record = scheduleDaoSupport.loadScheduleCancelRecord(courseSchedule);
                
                if(record == null) {
                    record = new CourseScheduleCancelRecord(courseSchedule, true);
                    
                    genericDaoSupport.save(record);
                }
            }
        }
        
        if(courseSchedule.getCourseType().isIndividual()) {
            courseSchedule.cancel();
            if(courseSchedule.getCourse().isExperience()) {
                String experienceHour = (Integer.parseInt(courseSchedule.getOccurHour().split(":")[0]) + 1) + ":" + courseSchedule.getOccurHour().split(":")[1];
                CoachRestCalendar experience = scheduleDaoSupport.loadCoachRestCalendar(coach, courseSchedule.getOccurDate(), experienceHour, CoachRestType.EXPERIENCE);
                if(experience != null) {
                    genericDaoSupport.update(experience.disable());
                }
            }
        } else if (courseSchedule.getCourseType().isYear()) {
            courseSchedule.disabled();
        }
        genericDaoSupport.update(courseSchedule);
        
        RoomScheduleRecord roomScheduleRecord = courseSchedule.getRoomSchedule();
        if(roomScheduleRecord != null) {
            genericDaoSupport.update(roomScheduleRecord.disabled());
        }
        
        scheduleDaoSupport.disableScheduleSmsNotice(courseSchedule);
    }
    
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.CourseScheduleService#generateScheduleQrCode(co.fitstart.entity.course.schedule.CourseSchedule, boolean)
     */
    public String generateScheduleQrCode(CourseSchedule courseSchedule, boolean validLocation) {
        
        String timestamp = String.valueOf(new Date().getTime());
        String qrcodeValue = com.demo2do.core.utils.StringUtils.connect(courseSchedule.getId().toString(), "|", timestamp);
        
        Result result = fileUploadHanlder.generateQrCode(qrcodeValue);
        
        if(result.isValid()) {
            
            CourseScheduleAttribute signinPersonName = new CourseScheduleAttribute(courseSchedule, Constant.VALID_SIGNIN_LOCATION, validLocation ? "是" : "否");
            genericDaoSupport.save(signinPersonName);
            
            return result.getData().get("key").toString();
        } else {
            throw new BusinessException("生成二维码失败");
        }
    }
    
    /**
     * 
     * @param coach
     * @param message
     */
    protected void createPrincipalMessage(Principal coach, String message) {
        PrincipalMessage principalMessage = new PrincipalMessage(coach);
        genericDaoSupport.save(principalMessage.initialize("课程变更", "您有新的课程变更信息", message));
    }
    
}
